<?php
class Epic_Paginator_Pagination
{		
	/**
	 * Total items
	 * @var int
	 */
	private $_totalItems = 0;
	
    /**
     * Items per a page
     * @var int
     */
    private $_itemsPerPage = 10;
    
    /**
     * Pages range
     * @var int
     */
    private $_pagesRange = 5;
    
    /**
     * Current page (start from 1)
     * @var int
     */
    private $_currentPage = 1;
    
    /**
     * Total Pages
     * @var int
     */
    private $_totalPages = 0;
    
    /**
     * Rrevious page
     * @var int
     */
   	public $_prevPage = 0;
    
    /**
     * Next page
     * @var int
     */
    public $_nextPage = 0;
    
    /**
     * Contructor
     * Set total items
     *
     * @param int $totalItems
     */
    public function __construct($totalItems = null) 
    {
		if (!is_null($totalItems)) {
			$this->setTotalItem($totalItems);
		}
    }
    
    /**
     * Set total items
     *
     * @param int $totalItem
     * @return Epic_Paginator_Pagination
     */
    public function setTotalItem($totalItems)
    {
    	$this->_totalItems = (int) $totalItems;
    	return $this;
    }
    
    /**
     * Retrive total items
     *
     * @return int
     */
    public function getTotalItems()
    {
    	return $this->_totalItems;
    }
    
    /**
     * Set items per page
     *
     * @param  int $itemsPerPage
     * @return Epic_Paginator_Pagination
     */
    public function setItemsPerPage($itemsPerPage)
    {
        $this->_itemsPerPage = (int) $itemsPerPage;
        return $this;
    }
    
    /**
     * Retrive items per page
     *
     * @return int
     */
    public function getItemsPerPage()
    {
    	return $this->_itemsPerPage;
    }
    
    /**
     * Set pages range
     *
     * @param  int $pagesRange
     * @return Epic_Paginator_Pagination
     */
    public function setPagesRange($pagesRange)
    {
    	$this->_pagesRange = (int) $pagesRange;
    	return $this;
    }
    
    /**
     * Retrive pages range
     *
     * @return int
     */
    public function getPagesRange()
    {
    	return $this->_pagesRange;
    }
    
    /**
     * Set curent page
     *
     * @param  int $currentPage current page number
     * @return Epic_Paginator_Pagination
     */
    public function setCurrentPage($currentPage)
    {
        $this->_currentPage = (int) $currentPage;
        return $this;
    }
    
    /**
     * Retrive curent page
     *
     * @return int
     */
    public function getCurrentPage()
    {
    	return $this->_currentPage;
    }
    
    /**
     * Retrive total pages
     *
     * @return int
     */
    public function getTotalPages()
    {
    	return $this->_totalPages;
    }
    
    /**
     * Retrive prev page
     *
     * @return int
     */
    public function getPrevPage()
    {
    	return $this->_prevPage;
    }
    
    /**
     * Retrive next page
     *
     * @return int
     */
    public function getNextPage()
    {
    	return $this->_nextPage;
    }
    
    /**
     * Returns a subset of pages within a given range.
     *
     * @param  int $lowerBound Lower bound of the range
     * @param  int $upperBound Upper bound of the range
     * @return array
     */
    protected function _getPagesInRange($lowerBound, $upperBound)
    {
       	$pages = array();
    
    	for ($currentPage = $lowerBound; $currentPage <= $upperBound; $currentPage++) {
    		$pages[$currentPage] = $currentPage;
    	}
    
    	return $pages;
    }
    
    /**
     * Need call before used Pagination
     * 
     * @return void
     */
    public function createPagination()
    {
    	$this->_totalPages  = (int) ceil($this->_totalItems / $this->_itemsPerPage);
    	$currentPage = $this->_currentPage;
    	
    	// Previous and next
    	if ($currentPage - 1 > 0) {
    		$this->_prevPage = $currentPage - 1;
    	}
    	
    	if ($currentPage + 1 <= $this->_totalPages) {
    		$this->_nextPage = $currentPage + 1;
    	}
    }
     
    /**
     * Retrive number pages real display
     *
     * @return array
     */
    public function getPages()
    {
    	$totalPages  = $this->_totalPages;
        $pagesRange = $this->_pagesRange;
        $currentPage = $this->_currentPage;
        
        if ($pagesRange > $totalPages) {
            $pagesRange = $totalPages;
        }
        
        $delta = ceil($pagesRange / 2);
        if ($currentPage - $delta > $totalPages - $pagesRange) {
            $lowerBound = $totalPages - $pagesRange + 1;
            $upperBound = $totalPages;
        } else {
            if ($currentPage - $delta < 0)
                $delta = $currentPage;
            $offset     = $currentPage - $delta;
            $lowerBound = $offset + 1;
            $upperBound = $offset + $pagesRange;
        }

        return $this->_getPagesInRange($lowerBound, $upperBound);
    }
}